#include "generic_scheduler.h"

Generic_Scheduler :: Generic_Scheduler () {
	processes = new list <Process> ();
}

Generic_Scheduler :: ~Generic_Scheduler () {
	delete processes;
}

void Generic_Scheduler :: read_in (string input_file) {
	ifstream file (input_file.c_str ());
	string line;

	if (file.is_open ()) {
		// Get rid of the first line (headers)
		getline (file, line);

		while (file.good ()) {
			getline (file, line);
			
			if (!line.empty ()) {
				Process * p = parse (line);

				if (p != NULL) {
					processes -> push_front (*p);
				}
			}
		}

		file.close ();
	} else {
		cout << "File could not be opened...";
	}
}

void Generic_Scheduler :: sort_processes () {
	list <Process> :: iterator it;

	cout << "before sorting..." << endl;
	for (it = processes -> begin (); it != processes -> end (); it++) {
		cout << it -> to_string() << endl;
	}
	Compare_Arrival ca;
	processes -> sort (ca);

	cout << "after sorting..." << endl;
	for (it = processes -> begin (); it != processes -> end (); it++) {
		cout << it -> to_string() << endl;
	}
}

// TODO : Method
void Generic_Scheduler :: show_gantt () {

}

Process * Generic_Scheduler :: parse (string info) {
	Process * result;
	int size = info.size ();
	char data [6][5];

	/* clear the memory of the char ** */
	for (int i = 0; i < 6; i++) {
		memset (data [i], '\0', 5);
	}

	/* break the string by splitting in tabs */
	int j = 0;
	int k = 0;

	for (int i = 0; i < size; i++) {
		if (info [i] == '\t') {
			j++;
			k = 0;
		} else {
			data [j][k] = info [i];
			k++;
		}
	}

	/* place into variables */
	int pid = atoi (data [0]);
	int burst = atoi (data [1]);
	int arrival = atoi (data [2]);
	int priority = atoi (data [3]);
	int deadline = atoi (data [4]);
	int io = atoi (data [5]);

	/* check to make sure that the data is good */
	bool is_good = true;

	// If any are negative, the process is invalid
	if (pid < 0) is_good = false;
	if (burst < 0) is_good = false;
	if (arrival < 0) is_good = false;
	if (priority < 0) is_good = false;
	if (deadline < 0) is_good = false;
	if (io < 0) is_good = false;

	// logic checks
	if (deadline <= arrival) is_good = false;
	
	if (is_good) {
		result = new Process (pid, burst, arrival, priority, deadline, io);
	} else {
		result = NULL;
	}

	return result;
}

void Generic_Scheduler :: start () {
	begin (processes);
}

bool Compare_Arrival::operator() (const Process & p1, const Process & p2) {
	bool result = false;

	if(p1.arrival <= p2.arrival) {
		result = true;
	}
	
	return result;
}
